-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement VRF route leaking #160
Conversation
22ac9f8
to
f74e335
Compare
2e85fd6
to
bee5ac2
Compare
internal/controller/api_to_config.go
Outdated
func validatePrefixes(prefixes []string) error { | ||
for _, p := range prefixes { | ||
family := ipfamily.ForCIDRString(p) | ||
if family == ipfamily.Unknown { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ipfamily.ForCIDRString(p) ==ipfamily.Unknown
just because family word is occuring too many times
internal/controller/api_to_config.go
Outdated
@@ -67,8 +67,37 @@ func apiToFRR(resources ClusterResources, alwaysBlock []net.IPNet) (*frr.Config, | |||
} | |||
|
|||
alwaysBlockFRR := alwaysBlockToFRR(alwaysBlock) | |||
prefixesForVRF := map[string][]string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought: that could be a type X with func newX(routers) X
and methods X.validate()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's "that"? the whole map or []string{} ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and yes, I agree it's borderline to be readeable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I mean the whole map[string][]string
but as is also ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left the type unchanged but hid the logic behind a couple of functions. Hoping it's readable. I don't feel hiding the map behind a type would be beneficial here.
internal/controller/api_to_config.go
Outdated
} | ||
|
||
// All prefixes available in this router: defined and imported from VRFs | ||
prefixesInRouter := sets.New(r.Prefixes...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why pick sets and not using standard library map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As much as I like sticking to the stdlib, sets are more convenient to get the output ordered (which we want, so the generated configuration is stable).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the sort the only reason?
but we already have maps for bfd, and sort function in the code base, therefore this introduce different approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we also use sets already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no I think you are right, here we don't even leverage the order. Let me switch to maps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or not !!! we rely on the order, reverting to set
@@ -384,6 +400,32 @@ func validateSelectorLengths(mask int, le, ge uint32) error { | |||
return nil | |||
} | |||
|
|||
func validateImportVRFs(r v1beta1.Router, allVRFs map[string][]string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible to have go coverage to see how much of this code is being unit-testes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can file an issue to add that, or do you think it relates to this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put random panics and unit-tests are still green, the error branch looks not really unit-tested. But a test coverage would give us precise what we miss.
git diff
diff --git a/internal/controller/api_to_config.go b/internal/controller/api_to_config.go
index 1b0f7a3..d166f9b 100644
--- a/internal/controller/api_to_config.go
+++ b/internal/controller/api_to_config.go
@@ -403,9 +403,15 @@ func validateSelectorLengths(mask int, le, ge uint32) error {
func validateImportVRFs(r v1beta1.Router, allVRFs map[string][]string) error {
for _, i := range r.Imports {
if i.VRF == "default" {
+ if true {
+ panic("")
+ }
continue
}
if _, ok := allVRFs[i.VRF]; !ok {
+ if true {
+ panic("")
+ }
return fmt.Errorf("router %d-%s imports vrf %s which is not defined", r.ASN, r.VRF, i.VRF)
}
}
@@ -619,6 +625,9 @@ func validatePrefixes(prefixes []string) error {
for _, p := range prefixes {
family := ipfamily.ForCIDRString(p)
if family == ipfamily.Unknown {
+ if true {
+ panic("")
+ }
return fmt.Errorf("unknown ipfamily for %s", p)
}
}
[I] kka@f-t14s ~/w/g/m/frr-k8s (leakvrf ✖1)> go test ./internal/controller/... -run=TestConversion/ -count=1
ok github.com/metallb/frr-k8s/internal/controller 0.023s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, I understand we are not covering, I am fine with extending but I don't want to add the coverage logic in CI here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not asking to add coverage ci logic, I am only asking if you can see the coverage once locally in your dev machine. The real ask is if you think we should more unit-test and cover allo the error branches that are not covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I think you covered a bit more in the latest push)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this done (curious though if you can run locally in your dev a coverage, I cannot due to the fact that controller unit test needs envtest way of running)
} | ||
for _, p := range n.ToAdvertise.Allowed.Prefixes { | ||
if !prefixesInRouter.Has(p) { | ||
return fmt.Errorf("trying to advertise non configured prefix %s to neighbor %s, vrf %s", p, neighborName(n.ASN, n.Address), routerConfig.VRF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log line could split the args into newline.
Also why do we need to error here? I mean that config might makes sense and allow user to filter out per neighbor in the allow prefix? Or is the FRR drops an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here we allow to advertise a given prefix to a neighbor. We want to tell the user, he thinks he's allowing a prefix that can't come from anywhere as it's not in the router's prefix or in any imported route from other vrfs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay I got it the otherway around :) that might be a feedback. Can I have in allow a prefix a /16
and overtime to add remove /24
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what do you mean by overtime. In general, with allow you must match something you have in hte prefix list (or you can have all).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I mean on day one user sets on the default vrf the allow prefix list to 10.10.0.0/16
, and in day X user adds the prefix in vrf red 10.10.10.0/24
(which is imported) and in day X+1 user in green the prefix 10.10.20.0/24
(which is imported). Is that a use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not exactly, as each configuration is meant to be self - contained. So, when you say default imports red, it really means import all the learned routes from red + advertise the prefixes defined locally in the stanza belonging to the red vrf.
}, | ||
err: nil, | ||
}, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
go test ./internal/controller/... -run=TestConversion/Multiple_Routers_import -v
=== RUN TestConversion
=== RUN TestConversion/Multiple_Routers_import_VRFs
=== RUN TestConversion/Multiple_Routers_import_VRF,_advertise_ips_from_the_imported_vrf
=== RUN TestConversion/Multiple_Routers_import_VRFs,_advertise
--- PASS: TestConversion (0.01s)
--- PASS: TestConversion/Multiple_Routers_import_VRFs (0.00s)
--- PASS: TestConversion/Multiple_Routers_import_VRF,_advertise_ips_from_the_imported_vrf (0.00s)
--- PASS: TestConversion/Multiple_Routers_import_VRFs,_advertise (0.00s)
PASS
I cannot tell the diff on the test by looking the description
Unless I am lost in the big file the first and third is the same, and probably the second is superset of the fist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it is:
--- PASS: TestConversion/Multiple_Routers_import_VRFs (0.00s)
--- PASS: TestConversion/Multiple_Routers_import_VRF,_advertise_ips_from_the_imported_vrf (0.00s)
--- PASS: TestConversion/Multiple_Routers_import_non_existing_VRFs (0.00s)
--- PASS: TestConversion/Multiple_Routers_import_VRF,_red_imports_default_and_advertises (0.00s)
first is only import with no advertisement. The ones with advertisements are supersets, but I think it still make sense to have them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
internal/controller/api_to_config.go
Outdated
// All prefixes available in this router: defined and imported from VRFs | ||
prefixesInRouter := sets.New(r.Prefixes...) | ||
for _, i := range r.Imports { | ||
importedPrefixes := prefixesForVRF[i.VRF] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is confusing e.g. assigning when the key is not there.
Maybe it be something like
key=i.VRF
if i.VRF="default" {key=""}
importePrefixes = prefixesForVRF[key]
- what happens if key does exist, should we check if
v,ok:= prefixesForVRF[key];!ok{}
- can we eliminate the transform from default? (maybe when create the original the "" to be "default")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem here is, frr wants "default" when importing, while in the api is cleaner not to bother about "default" VRF if you don't have to deal with VRFs at all. Because of that, I couldn't find a better way to do this translation. I think having a slimmer api has more value over this.
Re - key not existing I need to recheck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll find a way to make it clearer. The missing key can't happen because we validate that imported vrfs exist and we fill a record for each vrf, but I agree it's weak and we should at least log (or even better panic) if the key is not there as we think it cna't happen.
internal/controller/api_to_config.go
Outdated
if i.VRF == "default" { | ||
importedPrefixes = prefixesForVRF[""] | ||
} | ||
prefixesInRouter.Insert(importedPrefixes...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the behavior if two vrfs have same prefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'll have the same prefix twice which won't be a problem as they are used to understand what we can / can't advertise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it one or two lines in the final config? (this can be test entry)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually not, it's a set. So they'll be squashed
ip prefix-list 192.168.1.2-pl-ipv4 seq 1 deny any | ||
ipv6 prefix-list 192.168.1.2-pl-ipv4 seq 2 deny any | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we have a golden file without extra empty lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem is not related to the golden file but how the templates are generated. We need to tweak the "-" in the go template to reduce them, but it's not a fight that makes sense to fight in this PR.
I'll file an issue to track it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filed #170
internal/ipfamily/ipfamily.go
Outdated
res := []string{} | ||
for _, p := range prefixes { | ||
family := ForCIDRString(p) | ||
if family != familyToFilter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if ForCIDRString(p)!=familyFilter
} | ||
for _, p := range n.ToAdvertise.Allowed.Prefixes { | ||
if !prefixesInRouter.Has(p) { | ||
return fmt.Errorf("trying to advertise non configured prefix %s to neighbor %s, vrf %s", p, neighborName(n.ASN, n.Address), routerConfig.VRF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I mean on day one user sets on the default vrf the allow prefix list to 10.10.0.0/16
, and in day X user adds the prefix in vrf red 10.10.10.0/24
(which is imported) and in day X+1 user in green the prefix 10.10.20.0/24
(which is imported). Is that a use case?
@@ -384,6 +400,32 @@ func validateSelectorLengths(mask int, le, ge uint32) error { | |||
return nil | |||
} | |||
|
|||
func validateImportVRFs(r v1beta1.Router, allVRFs map[string][]string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not asking to add coverage ci logic, I am only asking if you can see the coverage once locally in your dev machine. The real ask is if you think we should more unit-test and cover allo the error branches that are not covered.
internal/controller/api_to_config.go
Outdated
return nil, err | ||
} | ||
|
||
routerPrefixes, err := importedPrefixes(r, routersPrefixes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having routerPrefixes
and routersPrefixes
and many Prefixes
makes the code less readable imo.
Maybe instead localPrefixes
, allPrefixes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also merge the importedPrefixes and validateImportVRFs and rename the function prefixesToImport
local, err: =getLocalPrefixesIfValid()
imported,err:=getPrefixToImportIfValid()
local=append(local, imported...)
Names are first random thought while reading the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also merge the importedPrefixes and validateImportVRFs and rename the function
prefixesToImport
local, err: =getLocalPrefixesIfValid() imported,err:=getPrefixToImportIfValid() local=append(local, imported...)
Names are first random thought while reading the code
This is quite messy already, and I'd rather keep the validation separate so it's clear we are not hiding much behind the courtains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having
routerPrefixes
androutersPrefixes
and manyPrefixes
makes the code less readable imo. Maybe insteadlocalPrefixes
,allPrefixes
let me try to find a better name
@@ -384,6 +400,32 @@ func validateSelectorLengths(mask int, le, ge uint32) error { | |||
return nil | |||
} | |||
|
|||
func validateImportVRFs(r v1beta1.Router, allVRFs map[string][]string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I think you covered a bit more in the latest push)
}, | ||
err: nil, | ||
}, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -2493,7 +2767,7 @@ func TestConversion(t *testing.T) { | |||
if test.err == nil && err != nil { | |||
t.Fatalf("expected no error, got %v", err) | |||
} | |||
if diff := cmp.Diff(frr, test.expected); diff != "" { | |||
if diff := cmp.Diff(frr, test.expected, cmpopts.EquateEmpty()); diff != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is EquateEmpty() needs to be in this commit or
in Conversion unit tests: remove the empty fields from expected
commit? (I do not mind staying here if the answer no)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added as part of this test addition, then I filed a commit for cleaning up the others. I could've gone the other way around (or add this with the extra fields and then clean those in a later commit). Didn't seem too bad :P
@@ -4,7 +4,6 @@ package routes | |||
|
|||
import ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About the commit message:
is there a them for the commit? like : word before : can be E2E or API, or Controller ?
maybe E2E: description
note: I did not understood that flag means the return bool value, is it valid term?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this done
@@ -0,0 +1,32 @@ | |||
// SPDX-License-Identifier:Apache-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general the pattern seems to E2E:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I have been missing the comments that I need to reword before submit the code review.
I am talking about the commit message it has E2E Tests: test
, the pattern in previous commits is only E2E:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this
e2etests/tests/import_vrf.go
Outdated
|
||
defer ginkgo.GinkgoRecover() | ||
updater, err := config.NewUpdater() | ||
Expect(err).NotTo(HaveOccurred()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is invalid Expect
https://onsi.github.io/ginkgo/#no-assertions-in-container-nodes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general assign stuff in the tree construction phase is not right
https://onsi.github.io/ginkgo/#mental-model-how-ginkgo-traverses-the-spec-hierarchy
e2etests/tests/import_vrf.go
Outdated
var _ = ginkgo.Describe("Leaked routes with import vrfs should work", func() { | ||
var cs clientset.Interface | ||
|
||
defer ginkgo.GinkgoRecover() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you know why this is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I probably copy / pasted. Let me remove it and see how it goes.
@@ -0,0 +1,32 @@ | |||
// SPDX-License-Identifier:Apache-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I have been missing the comments that I need to reword before submit the code review.
I am talking about the commit message it has E2E Tests: test
, the pattern in previous commits is only E2E:
|
||
updateAndCheckPeered(*config, peersDefault, peersVRF, frrsDefault, frrsVRF, ipFamily) | ||
|
||
ginkgo.By("validating") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this description does add real value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jokes aside, I like seeing a test split in the setup / validation and the By makes both easier to understand while the test is running and when we read it.
It makes the test go from big silence to "I am doing this right now" to knowing where it is, especially when running locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In well formed test the BeforeEach/JustBeforeEach is what should be before validating (but table driven kind of make it hard properly form the test because the Before each must have a specific to entry).
Imo running locally the test, you can have prints/delve/It to show the progress.
We can pick it in the issue so no action here
frrsDefault, peersDefault, neighborsDefault := initNeighbors(false, ipFamily) | ||
frrsVRF, peersVRF, neighborsVRF := initNeighbors(true, ipFamily) | ||
|
||
ginkgo.By("pairing with nodes") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be omitted
e2etests/tests/import_vrf.go
Outdated
frrsVRF, peersVRF, neighborsVRF := initNeighbors(true, ipFamily) | ||
|
||
ginkgo.By("pairing with nodes") | ||
pairWithNodes(frrsDefault, ipFamily, toAdvertise) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer is all ginkgo asser takes place not nested == function to return error and assert here
e2etests/tests/import_vrf.go
Outdated
|
||
} | ||
|
||
updateAndCheckPeered(*config, peersDefault, peersVRF, frrsDefault, frrsVRF, ipFamily) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
passing *config as argument does not look good, is it required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not? If the function accepts a value and doesn't expect to modify it, it should accept a pointer. On the other hand, I need to use deepcopy to be able to leverage baseConfig, and that returns a pointer. At some point in the stack I need to reference it. I will do when I get the deepcopy, so it's nicer.
} | ||
config.Spec.BGP.Routers[0].Neighbors[i].ToReceive.Allowed.Mode = allowMode | ||
} | ||
for i := range config.Spec.BGP.Routers[1].Neighbors { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here you use range to get the index, imo the thing should work
for _,n:=range xxx{
do something with n
}
If it is only to use the array itself a for loop is cleaner.
But the effort to make the first to work (pointers/nested structs etc) might not worth, and therefore keeping as is works for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if "do something with n" is actually changing n, range won't work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true because https://github.com/metallb/frr-k8s/blob/main/api/v1beta1/frrconfiguration_types.go#L78 is not an array of pointers, was that a design decision?
(no action needed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why it would be a better design decision for the api?
906e0c6
to
d1926fa
Compare
@@ -4,7 +4,6 @@ package routes | |||
|
|||
import ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this done
} | ||
config.Spec.BGP.Routers[0].Neighbors[i].ToReceive.Allowed.Mode = allowMode | ||
} | ||
for i := range config.Spec.BGP.Routers[1].Neighbors { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true because https://github.com/metallb/frr-k8s/blob/main/api/v1beta1/frrconfiguration_types.go#L78 is not an array of pointers, was that a design decision?
(no action needed)
|
||
updateAndCheckPeered(*config, peersDefault, peersVRF, frrsDefault, frrsVRF, ipFamily) | ||
|
||
ginkgo.By("validating") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In well formed test the BeforeEach/JustBeforeEach is what should be before validating (but table driven kind of make it hard properly form the test because the Before each must have a specific to entry).
Imo running locally the test, you can have prints/delve/It to show the progress.
We can pick it in the issue so no action here
@@ -384,6 +400,32 @@ func validateSelectorLengths(mask int, le, ge uint32) error { | |||
return nil | |||
} | |||
|
|||
func validateImportVRFs(r v1beta1.Router, allVRFs map[string][]string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this done (curious though if you can run locally in your dev a coverage, I cannot due to the fact that controller unit test needs envtest way of running)
@@ -79,6 +79,16 @@ type Router struct { | |||
// Prefixes is the list of prefixes we want to advertise from this router instance. | |||
// +optional | |||
Prefixes []string `json:"prefixes,omitempty"` | |||
|
|||
// Imports is the list of imports we want for this router / vrf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imports is the list of imports
, could be more readable to like is a list of VRFs from which to import their prefixes?
Here we add the simplest way to route from a VRF to the other, by using import vrf <vrfname>, which is a shortcut to leak routes from a vrf to the other using the vpn SAFI under the default VRF. Also, despite the fact that the import goes in the ipfamily stanza, we choose here to allow an import that includes both the v4 and the v6 family. Signed-off-by: Federico Paolinelli <[email protected]>
We introduce a new importVRFs field to list the vrfs imported to the v4 / v6 AFIs of a given router. Also, we implement the rendering of that field in the frr config. Signed-off-by: Federico Paolinelli <[email protected]>
Translating and merging the new field. Signed-off-by: Federico Paolinelli <[email protected]>
Instead of relying on the returned bool, we propagate the error and we assert on the error routes not found when we know the routes shouldn't be there. This makes triaging easier as the error is more descriptive than a bool. Signed-off-by: Federico Paolinelli <[email protected]>
Here we test leaking routes from / to VRFs with different types of allowed prefixes. Signed-off-by: Federico Paolinelli <[email protected]>
Now that we use EquateEmpty, the expected value can be shorter and more compact, making the tests easier to navigate and handle. Signed-off-by: Federico Paolinelli <[email protected]>
Leaking advertised networks doesn't work in FRR 9.1, so we disable the test. We will re-enable them once the CI is stable with FRR 10. Signed-off-by: Federico Paolinelli <[email protected]>
Is this a BUG FIX or a FEATURE ?:
What this PR does / why we need it:
By implementing import VRF, we allow routes defined in the RIB of a router related to a given VRF to be imported from another router tied to another VRF.
This is true for routes being received and being announced.
In case of routes being announced, we still limit the routes to all those defined in the "allowed outgoing" section of a given neighbor.
Special notes for your reviewer:
Release note: